﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using deepzoomAccess.DTDBService;
using IndicoInterface;
using System.IO;
using System.ServiceModel;

namespace deepzoomAccess
{
    /// <summary>
    /// Simple program to provide some maintence updates to the deep zoom database via the deep zoom service.
    /// </summary>
    class Program
    {
        static string serviceBinding = "TestingBinding"; // Default to running in development WCF host.

        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Usage();
                return;
            }

            ///
            /// Process the arguments
            /// 

            Stack<string> argStack = new Stack<string>();
            Queue<Action> whatWeShouldDo = new Queue<Action>();
            bool bindingSeen = false;

            for (int i = args.Length-1; i >= 0; i--)
            {
                argStack.Push(args[i]);
            }

            string argBeingProcessed = null;
            try
            {
                while (argStack.Count > 0)
                {
                    argBeingProcessed = argStack.Pop();
                    switch (argBeingProcessed)
                    {
                        case "ResetUnfinishedTalks":
                            whatWeShouldDo.Enqueue(() => ResetUnifinishedTalks());
                            break;

                        case "ResetTalk":
                            int id = Convert.ToInt32(argStack.Pop());
                            whatWeShouldDo.Enqueue(() => ResetTalk(id));
                            break;

                        case "RemoveTalk":
                            id = Convert.ToInt32(argStack.Pop());
                            whatWeShouldDo.Enqueue(() => RemoveTalk(id));
                            break;

                        case "Submit":
                            string url = argStack.Pop();
                            whatWeShouldDo.Enqueue(() => SubmitTalk(url));
                            break;

                        case "PrintURL":
                            id = Convert.ToInt32(argStack.Pop());
                            whatWeShouldDo.Enqueue(() => PrintURL(id));
                            break;

                        case "BindingLocalIIS":
                            if (bindingSeen)
                            {
                                Console.WriteLine("You can only use one binding on a command line!");
                                return;
                            }
                            serviceBinding = "LocalHTTPBinding";
                            bindingSeen = true;
                            break;

                        case "BindingProduction":
                            if (bindingSeen)
                            {
                                Console.WriteLine("You can only have one binding on a command line!");
                                return;
                            }
                            serviceBinding = "ProductionHTTPBinding";
                            bindingSeen = true;
                            break;

                        default:
                            Console.WriteLine("Unknown command '" + argBeingProcessed + "'");
                            Usage();
                            break;
                    }
                }
            }
            catch (Exception)
            {
                Console.WriteLine("Error in the arguments for '" + argBeingProcessed + "'!");
                Usage();
            }

            ///
            /// Now run the commands
            /// 

            while (whatWeShouldDo.Count != 0)
            {
                whatWeShouldDo.Dequeue()();
            }
        }

        /// <summary>
        /// Print out  atalk url.
        /// </summary>
        /// <param name="talkID"></param>
        private static void PrintURL(int talkID)
        {
            using (DTDBClient c = new DTDBClient(serviceBinding))
            {
                string xml = c.GetTalkXML(talkID);
                if (xml == null)
                {
                    Console.WriteLine("No such talk");
                }
                else
                {
                    var a = AgendaInfo.Deseralize(xml);
                    Console.WriteLine("Site: {0} SubDir: {1} ConfID: {2}", a.AgendaSite, a.AgendaSubDirectory, a.ConferenceID);
                }
            }
        }

        private static void SubmitTalk(string talkUrl)
        {
            AgendaInfo ai = new AgendaInfo(talkUrl);
            string agendaAsString = null;
            using (var tw = new StringWriter())
            {
                ai.Seralize(tw);
                agendaAsString = tw.ToString();
            }
            using (DTDBClient c = new DTDBClient(serviceBinding))
            {
                c.SubmitNewTalk(agendaAsString, "Not Yet Known", DateTime.Now); 
            }
            Console.WriteLine("Submitted Talk URL for rendering: " + talkUrl);
        }

        private static void RemoveTalk(int p)
        {
            using (DTDBClient c = new DTDBClient(serviceBinding))
            {
                if (!c.ValidTalkID(p))
                {
                    Console.WriteLine("That talk ID is not known by the system");
                    return;
                }
                DumpTalkInfo(c, p);
                c.RemoveTalk(p);
                Console.WriteLine("  -> Talks removed");
            }
        }

        /// <summary>
        /// Reset the rendering state for a particular talk ID.
        /// </summary>
        /// <param name="p"></param>
        private static void ResetTalk(int p)
        {
            using (DTDBClient c = new DTDBClient(serviceBinding))
            {
                if (!c.ValidTalkID(p))
                {
                    Console.WriteLine("That talk ID is not known by the system");
                    return;
                }
                c.ResetTalkStateToUnrendered(p);
                Console.WriteLine("Talks reset");
                DumpTalkInfo(c, p);
            }
        }

        /// <summary>
        /// List info about a particular talk.
        /// </summary>
        /// <param name="c"></param>
        /// <param name="p"></param>
        private static void DumpTalkInfo(DTDBClient c, int p)
        {
            Console.WriteLine("  -> ID " + p);
        }

        /// <summary>
        /// Reset all the vairous talks that are in the rendering state.
        /// </summary>
        private static void ResetUnifinishedTalks()
        {
            using (DTDBClient c = new DTDBClient(serviceBinding))
            {
                int[] talks = c.ResetRenderingTalks();
                if (talks != null && talks.Length != 0)
                {
                    Console.WriteLine("Reset the following talks");
                    foreach (var tid in talks)
                    {
                        DumpTalkInfo(c, tid);
                    }
                }
                else
                {
                    Console.WriteLine("No talk id's reset");
                }
            }
        }

        private static void Usage()
        {
            Console.WriteLine("Usage: deepzoomAccess ResetUnfinishedTalks - resets talks in the rendering state to be unrendered");
            Console.WriteLine("       deepzoomAccess ResetTalk <id> - resets talk <id> to be unrendered");
            Console.WriteLine("       deepzoomAccess RemoveTalk <id> - removes talk <id> from the database");
            Console.WriteLine("       deepzoomAccess Submit <url> - submits URL for rendering");
            Console.WriteLine("       deepzoomAccess PrintURL <id> - prints URL for the given talk");
            Console.WriteLine("");
            Console.WriteLine("       BindingLocalIIS - Uses local host on IIS for the service binding");
            Console.WriteLine("       BindingProduction - Uses local host on IIS for the service binding");
            Console.WriteLine("       <BindingDefault> - the program defaults to the local binding");
        }
    }

}
